﻿using H;
using H.Nets;
using System;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TaskManager
{
    public partial class MainForm : Form
    {
        private ITcpClient _Client;
        private CancellationTokenSource _CTS = null;

        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 连接服务器结点
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        private void Connect(string ip, int port)
        {
            if (_CTS != null)
            {
                return;
            }
            _CTS = new CancellationTokenSource();
            UpdateStatus(null);
            Task.Factory.StartNew(() =>
            {
                try
                {
                    _Client = IPlugin.GetObject<INetFactory>("H.Net")?.CreateTcpClientInstance(ip, port) ?? throw new Exception("无法创建TcpClient实例");

                    _Client.Recieved += (int topicID, int typeID, int dataLength, byte[] buffer) =>
                    {
                        string msg = Encoding.UTF8.GetString(buffer, 0, dataLength);
                        switch (typeID)
                        {
                            case HFrameType.Runtime.RUNNING_APP:
                                string[] lines = msg.Split('|');
                                Invoke(new Action(() =>
                                {
                                    LB_Main.DataSource = lines;
                                }));
                                break;
                            case HFrameType.FAIL:
                                MessageBox.Show(this, msg, "错误");
                                break;
                        }
                    };
                    _Client.StatusChange += (status) =>
                    {
                        UpdateStatus(status);
                        if (!status)
                        {
                            _Client = null;
                        }
                    };


                    _Client.Connect();
                }
                catch (Exception)
                {
                    //MessageBox.Show(err.Message);
                }
                finally
                {
                    _CTS = null;
                }
            }, _CTS.Token);
        }

        private void Disconnect()
        {
            _CTS?.Cancel();
            _Client?.Disconnect();
            _Client = null;
        }

        /// <summary>
        /// 更新连接状态
        /// </summary>
        /// <param name="status"></param>
        private void UpdateStatus(bool? status)
        {
            void _UpdateStatus()
            {
                if (status.HasValue)
                {
                    if (status.Value)
                    {
                        L_Status.Text = "已连接";
                        L_Status.ForeColor = Color.LightGreen;
                    }
                    else
                    {
                        L_Status.Text = "已断开";
                        L_Status.ForeColor = Color.Red;
                    }
                }
                else
                {
                    L_Status.Text = "连接中";
                    L_Status.ForeColor = Color.DarkGray;
                }
            }
            if (InvokeRequired)
            {
                Invoke(new Action(_UpdateStatus));
            }
            else
            {
                _UpdateStatus();
            }
        }


        #region 事件响应函数
        private void Bn_Refresh_Click(object sender, EventArgs e)
        {
            if (_Client == null)
            {
                return;
            }
            try
            {
                _Client.Send(_Client.CreateTopic(), HFrameType.Runtime.RUNNING_APP);
            }
            catch (Exception)
            {
                Console.WriteLine("发送指令失败");
            }
        }

        private void Bn_RunNew_Click(object sender, EventArgs e)
        {
            if (OFD_Main.ShowDialog() == DialogResult.OK)
            {
                string file = OFD_Main.FileName;

                try
                {
                    int typeID = HFrameType.Runtime.EXECUTE_APPNAME;
                    byte[] buffer = Encoding.UTF8.GetBytes($"{ file}#{ File.GetLastWriteTime(file).Ticks}#");
                    int dataLength = buffer.Length;

                    if (_Client.Exchange(_Client.CreateTopic(), ref typeID, ref dataLength, ref buffer))
                    {
                        if (typeID == HFrameType.Runtime.EXECUTE_APPBYTES)
                        {
                            using (MemoryStream ms = new MemoryStream())
                            using (BinaryWriter bw = new BinaryWriter(ms))
                            {
                                bw.Write(Path.GetFileName(file));
                                byte[] appBytes = File.ReadAllBytes(file);
                                bw.Write(appBytes.Length);
                                bw.Write(appBytes);
                                bw.Write("");

                                buffer = ms.ToArray();
                                _Client.BeginBulkTransfer(buffer.Length);
                                _Client.Send(HFrameType.Runtime.EXECUTE_APPBYTES, buffer.Length, buffer);
                                _Client.EndBulkTransfer();
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("发送指令失败");
                }
            }
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Disconnect();
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            Disconnect();
        }

        private void Button3_Click(object sender, EventArgs e)
        {
            Connect(TB_IP.Text, (int)NUD_Port.Value);
        }

        private void Bn_Kill_Click(object sender, EventArgs e)
        {
            if ((LB_Main.SelectedItem is string str) && int.TryParse(str.Split(',')[0], out int appID))
            {
                _Client.Send(_Client.CreateTopic(), HFrameType.Runtime.CLOSE_APP, 4, BitConverter.GetBytes(appID));
            }
        }

        private void Bn_Send_Click(object sender, EventArgs e)
        {
            if (_Client == null)
            {
                return;
            }
            _Client.Send(CB_TopicID.Checked ? (int)NUD_TopicID.Value : _Client.CreateTopic(), (int)NUD_TypeID.Value, TB_Text.Text);
            TB_Text.Text = null;
        }



        private void Bn_AllocConsole_Click(object sender, EventArgs e)
        {
            if (_Client == null)
            {
                return;
            }
            _Client.Send(_Client.CreateTopic(), HFrameType.Runtime.CONSOLE_ENABLE, 1, BitConverter.GetBytes(true));
        }

        private void TB_FreeConsole_Click(object sender, EventArgs e)
        {
            if (_Client == null)
            {
                return;
            }
            _Client.Send(_Client.CreateTopic(), HFrameType.Runtime.CONSOLE_ENABLE, 1, BitConverter.GetBytes(false));
        }

        private void TB_Text_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                Bn_Send.PerformClick();
            }
        }

        private void CB_TopicID_CheckedChanged(object sender, EventArgs e)
        {
            NUD_TopicID.Enabled = CB_TopicID.Checked;
        }

        private void NUD_Port_ValueChanged(object sender, EventArgs e)
        {
            Disconnect();
        }

        #endregion




    }
}
